﻿using CSRedis;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using ThresholdAssistant.ConfigSdk;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ThresholdAssistant.Redis
{
    /// <summary>
    /// Redis客户端管理器
    /// </summary>
    public static class RedisClientProvider
    {
        /// <summary>
        /// 对象锁
        /// </summary>
        private static readonly object @lock = new object();

        /// <summary>
        /// 默认的链接字符串名称
        /// </summary>
        private const string DefaultConnectionName = "CsRedisHost";

        /// <summary>
        /// 可客户字典列表
        /// </summary>
        private static Dictionary<string, CSRedisClient> ClientDic = new Dictionary<string, CSRedisClient>();

        /// <summary>
        /// 使用CsRedis
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="fileName">配置文件名称</param>
        /// <param name="fileDir">配置文件路径</param>
        /// <param name="connectionNames">连接名称列表</param>
        /// <returns></returns>
        public static IHostBuilder UseCsRedis(this IHostBuilder builder, string fileName = "", string fileDir = "", params string[] connectionNames)
        {
            return builder.ConfigureServices(services => services.UseCsRedis(fileName, fileDir, connectionNames));
        }

        /// <summary>
        /// 使用CsRedis
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="fileName">配置文件名称</param>
        /// <param name="fileDir">配置文件路径</param>
        /// <param name="connectionNames">连接名称列表</param>
        /// <returns></returns>
        public static IServiceCollection UseCsRedis(this IServiceCollection builder, string fileName = "", string fileDir = "", params string[] connectionNames)
        {
            InitClientDic(fileDir, fileName, connectionNames);
            return builder;
        }

        /// <summary>
        /// 使用RedisFactory
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="configs"></param>
        /// <returns></returns>
        public static IHostBuilder UseRedisFactory(this IHostBuilder builder, IDictionary<string, string> configs)
        {
            builder.ConfigureServices(service => service.AddSingleton<IRedisClientFactory>(x => new RedisClientFactory(configs)));
            return builder;
        }

        /// <summary>
        /// 使用RedisFactory
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="configs"></param>
        /// <returns></returns>
        public static IServiceCollection UseRedisFactory(this IServiceCollection builder, IDictionary<string, string> configs)
        {
            builder.AddSingleton<IRedisClientFactory>(x => new RedisClientFactory(configs));
            return builder;
        }


        /// <summary>
        /// 获取客户端信息
        /// </summary>
        /// <param name="connectionName">连接字符串名称</param>
        public static CSRedisClient GetRedisClient(string connectionName = DefaultConnectionName)
        {
            return ClientDic[connectionName];
        }

        /// <summary>
        /// 初始化连接字符串字典
        /// </summary>
        /// <param name="fileDir"></param>
        /// <param name="fileaName"></param>
        /// <param name="connectionNames"></param>
        private static void InitClientDic(string fileDir = "", string fileaName = "", params string[] connectionNames)
        {
            if (string.IsNullOrEmpty(fileDir))
            {
                fileDir = AppContext.BaseDirectory;
            }

            if (string.IsNullOrEmpty(fileaName))
            {
                fileaName = AppJson.FileName;
            }

            if (connectionNames == null || !connectionNames.Any())
            {
                //如果没传配置名称的情况下，使用默认的配置名称
                connectionNames = new string[] { DefaultConnectionName };
            }

            foreach (var connectionName in connectionNames)
            {
                var connectionString = ConfigUtil.GetValue(fileDir, fileaName, connectionName);
                if (!ClientDic.ContainsKey(connectionName))
                {
                    lock (@lock)
                    {
                        if (!ClientDic.ContainsKey(connectionName))
                        {
                            var dbConnectionString = $"{connectionString.TrimEnd(',', ';')}";
                            if (!dbConnectionString.Contains("defaultDatabase", StringComparison.InvariantCultureIgnoreCase))
                            {
                                //默认走db0
                                dbConnectionString += ",defaultDatabase=0";
                            }
                            ClientDic.Add(connectionName, new CSRedisClient(dbConnectionString));
                        }
                    }
                }
            }
        }
    }
}